﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using Newtonsoft.Json;

namespace XLB.ExtensionMethodCore
{
    /// <summary>
    /// 常用方法与常用扩展方法
    /// </summary>
    public static class XLBCommon
    {

        /// <summary>
        /// object转int
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static int ToInt(this object message)
        {
            int result;
            if (message == null || message.ToString().Trim() == "")
            {
                result = 0;
            }
            else
            {
                if (!int.TryParse(message.ToString(), out result))
                {
                    result = 0;
                }
            }
            return result;
        }

        /// <summary>
        /// 生成指定长度的真随机数
        /// </summary>
        /// <param name="length">随机数长度</param>
        /// <returns></returns>
        public static string Random(int length)
        {
            int t = 0;
            if (length <= 0)
            {
                return "长度不能为空";
            }
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            t = BitConverter.ToInt32(bytes, 0);
            Random rnd = new Random(t);

            string buffer = "0123456789";
            int range = buffer.Length;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(buffer.Substring(rnd.Next(range), 1));
            }
            return sb.ToString();
        }



        /// <summary>
        /// datatable转list
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static List<T> ToList<T>(this DataTable dt)
        {
            var list = new List<T>();
            var plist = new List<PropertyInfo>(typeof(T).GetProperties());
            if (dt == null || dt.Rows.Count <= 0)
            {
                return default(List<T>);
            }
            foreach (DataRow item in dt.Rows)
            {
                T s = Activator.CreateInstance<T>();
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    PropertyInfo info = plist.Find(p => p.Name == dt.Columns[i].ColumnName);
                    if (info != null)
                    {
                        try
                        {
                            if (!Convert.IsDBNull(item[i]))
                            {
                                object v = null;
                                if (info.PropertyType.ToString().Contains("System.Nullable"))
                                {
                                    v = Convert.ChangeType(item[i], Nullable.GetUnderlyingType(info.PropertyType));
                                }
                                else
                                {
                                    v = Convert.ChangeType(item[i], info.PropertyType);
                                }
                                info.SetValue(s, v, null);
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("字段【" + info.Name + "】转换出错：" + ex.Message);
                        }
                    }
                }
                list.Add(s);
            }
            return list;

        }

        /// <summary>
        /// IEnumerable转datatable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(this IEnumerable<T> collection)
        {
            if (collection == null)
            {
                return null;
            }
            var props = typeof(T).GetProperties();
            var dt = new DataTable();
            dt.Columns.AddRange(props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray());
            if (collection.Count() > 0)
            {
                for (int i = 0; i < collection.Count(); i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in props)
                    {
                        object obj = pi.GetValue(collection.ElementAt(i), null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    dt.LoadDataRow(array, true);
                }
            }
            return dt;
        }

        /// <summary>
        /// datatable列转行
        /// </summary>
        /// <param name="dataTable">被转换数据源</param>
        /// <param name="NoConertColumnNames">无需被转换的列</param>
        /// <param name="ColumnNames">需要新生成的列名</param>
        /// <param name="FieldName">转换列时需要被截取的部分字符串</param>
        /// <returns></returns>
        public static DataTable ColumnToRowConversion(this DataTable dataTable, string[] NoConertColumnNames, string[] ColumnNames, string FieldName)
        {
            /*
             调用示例
            string[] NoConertColumnNames = { "FirmName", "ProjectName" };
            string[] ColumnNames = { "Mater", "Value" };

            var res = dt.ColumnToRowConversion(NoConertColumnNames, ColumnNames, "Mater");
             */

            DataTable dt = new DataTable();

            #region 组装列
            for (int i = 0; i < NoConertColumnNames.Length; i++)
            {
                dt.Columns.Add(NoConertColumnNames[i], typeof(string));
            }
            for (int i = 0; i < ColumnNames.Length; i++)
            {
                dt.Columns.Add(ColumnNames[i], typeof(string));
            }
            #endregion

            #region 组装数据
            if (dataTable.Rows.Count > 0)
            {
                foreach (DataRow item in dataTable.Rows)
                {
                    foreach (DataColumn colum in dataTable.Columns)
                    {
                        var row = dt.NewRow();
                        //固定列
                        for (int i = 0; i < NoConertColumnNames.Length; i++)
                        {
                            row[NoConertColumnNames[i]] = item[NoConertColumnNames[i]];
                        }
                        //动态列
                        if (!NoConertColumnNames.Contains(colum.ColumnName))
                        {
                            for (int i = 0; i < ColumnNames.Length; i++)
                            {
                                if (ColumnNames[i].StartsWith(FieldName))
                                {
                                    //列名
                                    row[ColumnNames[i]] = colum.ColumnName.Replace(FieldName + "_", "");
                                }
                                else
                                {
                                    row[ColumnNames[i]] = item[colum.ColumnName];  //值
                                }


                            }
                        }

                        if (!string.IsNullOrEmpty(row[FieldName].ToString()))
                        {
                            dt.Rows.Add(row);
                        }

                    }
                }
            }
            #endregion

            return dt;
        }

        /// <summary>
        /// 是否为电子邮件
        /// </summary>
        public static bool IsEmail(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            const string pattern = @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$";
            return Regex.IsMatch(value, pattern);
        }

        /// <summary>
        /// 是否是IP地址
        /// </summary>
        public static bool IsIpAddress(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            else
            {
                const string pattern = @"^(\d(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\d\.){3}\d(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\d$";
                return Regex.IsMatch(value, pattern);
            }

        }

        /// <summary>
        /// 是否是整数
        /// </summary>
        public static bool IsNumeric(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            const string pattern = @"^\-?[0-9]+$";
            return Regex.IsMatch(value, pattern);
        }

        /// <summary>
        /// 是否是Unicode字符串
        /// </summary>
        public static bool IsUnicode(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            const string pattern = @"^[\u4E00-\u9FA5\uE815-\uFA29]+$";
            return Regex.IsMatch(value, pattern);
        }

        /// <summary>
        /// 是否Url字符串
        /// </summary>
        public static bool IsUrl(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            const string pattern = @"^(http|https|ftp|rtsp|mms):(\/\/|\\\\)[A-Za-z0-9%\-_@]+\.[A-Za-z0-9%\-_@]+[A-Za-z0-9\.\/=\?%\-&_~`@:\+!;]*$";
            return Regex.IsMatch(value, pattern);
        }

        /// <summary>
        /// 是否身份证号，验证如下3种情况：
        /// 1.身份证号码为15位数字；
        /// 2.身份证号码为18位数字；
        /// 3.身份证号码为17位数字+1个字母
        /// </summary>
        public static bool IsIdentityCard(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            const string pattern = @"^(^\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$";
            return Regex.IsMatch(value, pattern);
        }

        /// <summary>
        /// 是否手机号码
        /// </summary>
        /// <param name="value"></param>
        /// <param name="isRestrict">是否按严格格式验证</param>
        public static bool IsMobileNumber(this string value, bool isRestrict = false)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            string pattern = isRestrict ? @"^[1][3-8]\d{9}$" : @"^[1]\d{10}$";
            return Regex.IsMatch(value, pattern);
        }

        /// <summary>
        /// 将值为null或者string.empty的字符串转换为stirng.empty
        /// </summary>
        /// <param name="message">需要转换的字符串</param>
        /// <returns></returns>
        public static string NullOrEmptyToEmpty(this string message)
        {
            return !string.IsNullOrEmpty(message) ? message : string.Empty;
        }

        /// <summary>
        /// 將datarow转换为实体
        /// </summary>
        /// <typeparam name="T">返回的实体类型</typeparam>
        /// <param name="r">datarow数据集</param>
        /// <returns>需要返回的实体</returns>
        public static T ToModel<T>(this DataRow r)
        {
            T t = default(T);
            if (r != null)
            {
                t = Activator.CreateInstance<T>();
                PropertyInfo[] ps = t.GetType().GetProperties();
                foreach (var item in ps)
                {
                    if (r.Table.Columns.Contains(item.Name))
                    {
                        object v = r[item.Name];
                        if (v.GetType() == typeof(System.DBNull))
                            v = null;
                        item.SetValue(t, v, null);
                    }
                }
            }
            return t;
        }

        /// <summary>
        /// 将图片以二进制流
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string SaveImage(String path)
        {
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); //将图片以文件流的形式进行保存
            BinaryReader br = new BinaryReader(fs);
            byte[] imgBytesIn = br.ReadBytes((int)fs.Length); //将流读入到字节数组中
            Encoding myEncoding = Encoding.GetEncoding("utf-8");

            string stImageByte = Convert.ToBase64String(imgBytesIn);
            return stImageByte;
        }
        /*
        /// <summary>
        /// 现实二进制流代表的图片
        /// </summary>
        /// <param name="stImageByte"></param>
        public static void ShowImgByByte(string stImageByte)
        {
            string NewImageName = "AAAA";//ImageName(CenterId);//获得图片的名字
            string ImagePath = @"C:/WorkToXLB/LearnCode/XLB.ExtensionMethodCore/src/XLB.ExtensionMethodCore/XLB.ExtensionMethodCore.Test/img/" + NewImageName.ToString() + ".jpg";

            byte[] imgBytesIn = Convert.FromBase64String(stImageByte);
            MemoryStream ms = new MemoryStream(imgBytesIn);

            Bitmap bmp = new Bitmap(ms);
            bmp.Save(ImagePath, ImageFormat.Bmp);
            ms.Close();
        }
        */
        /// <summary>
        /// 获取指定数据实体中字段名、字段值、字段类型信息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static List<ModelPropertyValueEntity> GetProperties<T>(T t)
        {
            List<ModelPropertyValueEntity> list = new List<ModelPropertyValueEntity>();

            //var ret = new Dictionary<object, object>();
            if (t == null) { return null; }
            PropertyInfo[] properties = t.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            if (properties.Length <= 0) { return null; }
            foreach (PropertyInfo item in properties)
            {
                string name = item.Name;
                object value = item.GetValue(t, null);
                var type = "";
                if (item.PropertyType == typeof(DateTime?))
                {
                    type = "DateTime?";
                }
                else if (item.PropertyType == typeof(DateTime))
                {
                    type = "DateTime";
                }
                else if (item.PropertyType == typeof(decimal?))
                {
                    type = "decimal?";
                }
                else if (item.PropertyType == typeof(decimal))
                {
                    type = "decimal";
                }
                else if (item.PropertyType == typeof(int?))
                {
                    type = "int?";
                }
                else if (item.PropertyType == typeof(double?))
                {
                    type = "double?";
                }
                else if (item.PropertyType == typeof(double))
                {
                    type = "double";
                }
                else if (item.PropertyType == typeof(float?))
                {
                    type = "float?";
                }
                else if (item.PropertyType == typeof(float))
                {
                    type = "float";
                }
                else if (item.PropertyType == typeof(string))
                {
                    type = "string";
                }
                else
                {
                    type = item.PropertyType.Name;
                }

                if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String"))
                {
                    list.Add(new ModelPropertyValueEntity { name = name, value = value, type = type });
                }
            }
            return list;
        }

        #region 数据库语句相关
        /*
        /// <summary>
        /// 根据实体生成添加sql语句
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="info"></param>
        /// <param name="tablename">需要生成的sql server表名</param>
        /// <returns>返回内容为【string】类型的语句和【SqlParameter[]】类型的sql参数</returns>
        public static SQLResult ToAddSqlSentence<T>(this T info, string tablename)
        {
            SQLResult result = new SQLResult();
            StringBuilder strSql = new StringBuilder();
            List<SqlParameter> sqlPars = new List<SqlParameter>();
            List<Parameter> pars = getProperties(info);
            if (pars != null)
            {
                string fieldName = string.Empty;
                string fieldPars = string.Empty;
                string fieldValue = string.Empty;
                strSql.Append("Insert Into @tablename (");
                for (int i = 0; i < pars.Count; i++)
                {
                    if (pars[i].Value != null)
                    {
                        fieldName += pars[i].Name + ",";
                        fieldPars += "@" + pars[i].Name + ",";
                    }
                }
                strSql.Append(fieldName.TrimEnd(','));
                strSql.Append(") values (");
                strSql.Append(fieldPars.TrimEnd(','));
                strSql.Append(")");
                for (int i = 0; i < pars.Count; i++)
                {
                    if (pars[i].Value != null)
                    {
                        sqlPars.Add(new SqlParameter("@" + pars[i].Name, pars[i].Value));
                    }
                }
            }
            result.SqlSentence = strSql.ToString();
            result.SqlParameters = sqlPars.ToArray();
            return result;
        }

        /// <summary>
        /// 根据实体生成更新sql语句
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="info"></param>
        /// <param name="tablename">需要生成的sql server表名</param>
        /// <param name="WhereName">where字段名称</param>
        /// <param name="WhereValue">where字段值</param>
        /// <returns>返回内容为【string】类型的语句和【SqlParameter[]】类型的sql参数</returns>
        public static SQLResult ToEditSqlSentence<T>(this T info, string tablename, string WhereName = "", string WhereValue = "")
        {
            List<SqlParameter> sqlPars = new List<SqlParameter>();
            StringBuilder strSql = new StringBuilder();
            SQLResult result = new SQLResult();
            if (info != null)
            {
                strSql.Append("update @tablename set ");
                sqlPars.Add(new SqlParameter("@tablename", tablename));
                List<Parameter> pars = getProperties(info);
                if (pars != null)
                {
                    for (int i = 0; i < pars.Count; i++)
                    {
                        if (!string.IsNullOrEmpty(pars[i].Name) && !string.IsNullOrEmpty(pars[i].SqlPar) && pars[i].Value != null)
                        {

                            if (i == 0)
                            {
                                strSql.Append(string.Format("{0}={1} ", pars[i].Name, pars[i].SqlPar));
                            }
                            else
                            {
                                strSql.Append(string.Format(",{0}={1}", pars[i].Name, pars[i].SqlPar));
                            }
                            SqlParameter sqlPar = new SqlParameter();
                            sqlPar.ParameterName = pars[i].SqlPar;
                            sqlPar.Value = pars[i].Value;
                            sqlPars.Add(sqlPar);
                        }
                    }

                    if (!string.IsNullOrEmpty(WhereName) && !string.IsNullOrEmpty(WhereValue))
                    {
                        strSql.Append(string.Format(" where {0}=@{0}", WhereName));
                        sqlPars.Add(new SqlParameter("@" + WhereName, WhereValue));
                    }
                }
                result.SqlSentence = strSql.ToString();
                result.SqlParameters = sqlPars.ToArray();
            }
            return result;
        }
        */
        /// <summary>
        /// 遍历获取类的属性及属性的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        private static List<Parameter> getProperties<T>(T t)
        {
            List<Parameter> list = new List<Parameter>();
            if (t == null)
            {
                return null;
            }
            System.Reflection.PropertyInfo[] properties = t.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);


            if (properties.Length <= 0)
            {
                return null;
            }
            foreach (System.Reflection.PropertyInfo item in properties)
            {
                Parameter par = new Parameter();
                string name = item.Name;
                object value = item.GetValue(t, null);
                if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String"))
                {
                    par.Name = name;
                    par.SqlPar = "@" + name;
                    par.Value = value;
                }
                else
                {
                    getProperties(value);
                }
                list.Add(par);
            }
            return list;
        }

        /// <summary>
        /// SQL参数类
        /// </summary>
        private struct Parameter
        {
            /// <summary>
            /// 字段名
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// sql参数
            /// </summary>
            public string SqlPar { get; set; }
            /// <summary>
            /// 字段值
            /// </summary>
            public object Value { get; set; }
        }

        ///// <summary>
        ///// 返回结果类
        ///// </summary>
        //public class SQLResult
        //{
        //    /// <summary>
        //    /// sql语句
        //    /// </summary>
        //    public string SqlSentence { get; set; }
        //    /// <summary>
        //    /// sql参数
        //    /// </summary>
        //    public SqlParameter[] SqlParameters { get; set; }
        //}
        #endregion
    }
}
